package com.nlp.fresh_comp;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.nlp.fresh_comp.model.TItem;
import com.nlp.fresh_comp.model.TUser;
import com.nlp.fresh_comp.utils.FileUtils;

public class StatisticsProcess {
	Map<String, int[] > itemStat = null;
	Map<Integer, int[] > catStat = null;
	Map<String, Integer> itemCat = null;
	
	Map<String,TItem> itemSet = null;
	
	String path ="D:\\j2ee\\fresh_comp\\src\\main\\resources\\fresh_comp_offline\\";
	
	public void loadItem() throws Exception{
		List<String> strs = FileUtils.readFileData(path + "tianchi_fresh_comp_train_item.csv");
		if( strs.isEmpty() ){
			return;
		}
		itemSet = new HashMap<String,TItem>(strs.size() );
		int lineNum = 0;
		for (String string : strs) {
			lineNum++;
			if( lineNum == 1 || string.isEmpty() ){
				continue;
			}
			TItem item = new TItem(string);
			itemSet.put(item.getItem_id(), item);
		}
	}
	
	public void reload(){
		BufferedReader br = new BufferedReader(new InputStreamReader(
				TrainDataProcess.class.getClassLoader().getResourceAsStream(
						"fresh_comp_offline/tianchi_fresh_comp_train_user.csv")));
		itemStat = new HashMap<String, int[] >();
		catStat = new HashMap<Integer, int[] >();
		itemCat = new HashMap<String,Integer>();
		try {
			String line = null;
			int lineNum = 0;
			List<TUser> list = null;
			String preId = null;
			FileWriter file = new FileWriter(new File(path+"user.txt"));
			FileWriter m1 = new FileWriter(new File(path+"m1.txt"));
			FileWriter base = new FileWriter(new File(path + "tianchi_mobile_recommendation_predict.csv"));
			base.write("user_id,item_id\n");
			while (br.ready()) {
				lineNum++;
				line = br.readLine().trim();
				if( lineNum == 1 || line == null || line.length() == 0 ){
					continue;
				}
				if( lineNum % 100 == 0 ){
					System.out.println(lineNum);
				}
				TUser action = new TUser(line);
				
				itemCat.put(action.getItem_id(), action.getItem_category());
				//新用户
				if (preId == null || !action.getUser_id().equals(preId) ) {
					baseLine(list, base);
					
					preId = action.getUser_id();
					//统计用户特征
					userStatistics(list, file);
					//统计商品及商品品类特征
					itemStatistics(list);
					
					getTrainData(list, m1);
					
					list = new ArrayList<TUser>();
				}
				list.add(action);
			}
			br.close();
			file.close();
			m1.close();
			base.close();
			itemStatisticsWriter();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void itemStatisticsWriter() throws IOException{
		FileWriter item = new FileWriter(new File(path+"item.txt"));
		for (Entry<String, int[] > entry : itemStat.entrySet()) {
			String str = entry.getKey();
			int action[] = entry.getValue();
			//购买比
			for (int i : action) {
				if( i != 0 ){
					str += " " + ( action[3] / (i+0.0) );
				}else{
					str = str + " -1";
				}
			}
			//平均销量
			str += " " + ( action[3] / 30.0 );
			//商品购买量占比类别购买量、商品访问量占比类别访问量
			Integer cat = itemCat.get(entry.getKey());
			int[] catAction = catStat.get( cat );
			if( catAction != null && catAction[3] != 0 )
			{
				str += " " + ( action[3] / (catAction[3]+0.0) );
				str += " " + ( action[0] / (catAction[0]+0.0) );
			}else{
				str = str + " -1";
				str = str + " -1";
			}
			item.write(str + "\n");
		}
		item.close();
		
		FileWriter cat = new FileWriter(new File(path+"cat.txt"));
		for (Entry<Integer, int[] > entry : catStat.entrySet()) {
			Integer catid = entry.getKey();
			String str = catid + "";
			int action[] = entry.getValue();
			//购买比
			for (int i : action) {
				if( i != 0 ){
					str += " " + ( action[3] / (i+0.0) );
				}else{
					str = str + " -1";
				}
			}
			//平均销量
			str += " " + ( action[3] / 30.0 );
			
			cat.write(str + "\n");
		}
		cat.close();
	}
	
	public void itemStatistics( List<TUser> actions ){
		if( actions == null || actions.size() == 0 ){
			return;
		}
		for (TUser tUser : actions) {
			int action[] = itemStat.get(tUser.getItem_id() );
			if( action == null ){
				action = new int[4];
				for (int i : action) {
					i = 0;
				}
				itemStat.put(tUser.getItem_id(), action);
			}
			action[0] = tUser.getBehavior_type() == 1 ? (action[0]+1) : action[0];
			action[1] = tUser.getBehavior_type() == 2 ? (action[1]+1) : action[1];
			action[2] = tUser.getBehavior_type() == 3 ? (action[2]+1) : action[2];
			action[3] = tUser.getBehavior_type() == 4 ? (action[3]+1) : action[3];
			
			int[] actionCat = catStat.get( tUser.getItem_category() );
			if( actionCat == null ){
				actionCat = new int[4];
				for (int i : actionCat) {
					i = 0;
				}
				catStat.put(tUser.getItem_category(), actionCat);
			}
			actionCat[0] = tUser.getBehavior_type() == 1 ? (actionCat[0]+1) : actionCat[0];
			actionCat[1] = tUser.getBehavior_type() == 2 ? (actionCat[1]+1) : actionCat[1];
			actionCat[2] = tUser.getBehavior_type() == 3 ? (actionCat[2]+1) : actionCat[2];
			actionCat[3] = tUser.getBehavior_type() == 4 ? (actionCat[3]+1) : actionCat[3];
		}
	}
	
	public void userStatistics( List<TUser> actions, FileWriter file ) throws IOException{
		if( actions == null || actions.size() == 0 ){
			return;
		}
		int action[] = new int[4];
		for (int i : action) {
			i = 0;
		}
		for (TUser tUser : actions) {
			action[0] = tUser.getBehavior_type() == 1 ? (action[0]+1) : action[0];
			action[1] = tUser.getBehavior_type() == 2 ? (action[1]+1) : action[1];
			action[2] = tUser.getBehavior_type() == 3 ? (action[2]+1) : action[2];
			action[3] = tUser.getBehavior_type() == 4 ? (action[3]+1) : action[3];
		}
		String str = actions.get(0).getUser_id();
		for (int i : action) {
			if( i != 0 ){
				str += " " + ( action[3] / (i+0.0) );
			}else{
				str = str + " -1";
			}
		}
		file.write(str + "\n");
	}
	
	public void getTrainData( List<TUser> actions, FileWriter m1 ) throws IOException{
		if( actions == null || actions.size() == 0 ){
			return;
		}
		Set<String> itemSet = new HashSet<String>();
		for (TUser tUser : actions) {
			//m1号训练数据
			itemSet.add( tUser.getItem_id() );
			if( tUser.getBehavior_type() == 3 
					&& ( tUser.getTime().getDate() == 17 && tUser.getTime().getMonth() == 12 ) ){
				TUser id = null;
				//17号加入购物车，18号购买情况
//				List<TUser> catAction = new ArrayList<TUser>();
//				List<TUser> itemAction = new ArrayList<TUser>();
				for (int i = 0; i < actions.size(); i++ ) {
					TUser action = actions.get(i);
					
//					if( action.getItem_id().equals(tUser.getItem_id()) && action != tUser ){
//						itemAction.add(action);
//					}
//					if(  action.getItem_category() == tUser.getItem_category() && action != tUser  ){
//						catAction.add(action);
//					}
					
					if(tUser.getItem_id().equals(action.getItem_id()) && action.getBehavior_type() == 4 
							&& ( tUser.getTime().getDate() == 18 && tUser.getTime().getMonth() == 12 ) ){
						id = action;
					}
				}
				
				if( id == null ){
					//负例
					m1.write("-1 " + tUser.getUser_id() + " " + tUser.getItem_id() + "\n");
				}else{
					//正例
					m1.write("1 " + tUser.getUser_id() + " " + tUser.getItem_id() + "\n");
				}
			}
		}
	}
	
	public void actionCatFeature( List<TUser> catAction ){
		
	}
	
	public void actionItemFeature( List<TUser> actionList, TUser itemAction ){
		if( actionList == null || actionList.size() == 0 ){
			return;
		}
		//是否购买过该商品
		boolean buy = false; int day = -1; int buyFreq = 0; //是否购买、距离现在多久、购买频次
		
		for (TUser tUser : actionList) {
			if( itemAction.getItem_id().equals(tUser.getItem_id()) && itemAction != tUser ){
				//相同商品
				
			}else if( itemAction.getItem_category() == tUser.getItem_category() && itemAction != tUser  ){
				//同类商品
				
			}
			
			
		}
	}
	
	public void baseLine( List<TUser> actions, FileWriter file) throws IOException{
		if( actions == null || actions.size() == 0 ){
			return;
		}
		Map<String, Double> base = new HashMap<String, Double>();
		for (TUser tUser : actions) {
			if( tUser.getTime().getMonth() == 11 && tUser.getTime().getDate() > 15 ){
				int score = (tUser.getBehavior_type() == 4) ? -100:tUser.getBehavior_type();
				
				if( base.containsKey(tUser.getItem_id()) ){
					base.put(tUser.getItem_id(), base.get(tUser.getItem_id()) + score*tUser.getTime().getDate() / 18.0 );
				}else{
					base.put(tUser.getItem_id(), score*tUser.getTime().getDate() /18.0 );
				}
			}
		}
		//排序
		List<Map.Entry<String,Double>> mappingList = new ArrayList<Map.Entry<String,Double> >(base.entrySet());
		Collections.sort(mappingList, new Comparator<Map.Entry<String,Double>>(){ 
			   public int compare(Map.Entry<String,Double> mapping1,Map.Entry<String,Double> mapping2){ 
			    return 0 - mapping1.getValue().compareTo(mapping2.getValue()); 
			   } 
		}); 
		int num = (int) (mappingList.size() * 0.3);
		num = (num==0)? 1 : ( ( num > 3 ) ? 3 : num );
		int pre = 0;
		for (Entry<String, Double> entry : mappingList ) {
			if( itemSet.containsKey(entry.getKey()) ){
				if( entry.getValue().compareTo(3.0)< 0 || pre >= num ){
					break;
				}
				pre++;
				file.write( actions.get(0).getUser_id() + "," + entry.getKey()  + "\n" );
			}
		}
	}
	
	public static void main(String[] args) throws Exception {
		StatisticsProcess process = new StatisticsProcess();
		process.loadItem();
		process.reload();
	}
}
